﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using Sausage.Common;
using Sausage.Web.Code;
using Sausage.Web.DataModel;
using Sausage.Web.Models;
using Telerik.Web.Mvc;

namespace Sausage.Web.Domain
{
    public class MaintainMachineHelper
    {

        public static GridModel<object> Select(JosnPagingQueryModel query)
        {
            Guid targetID;
            var isWithChild = Helper.IsNeedOrganizationQuery(query, out targetID);
            List<Guid> organization =OrganizationHelper.GetAllowedOrganizationList(isWithChild, targetID);

            using (var context = new SausageEntities())
            {   
                return
                    QueryMaintainMachine(
                        context.MaintainMachine.Where(
                            item =>
                            organization.Contains(item.OrganizationID) &&
                            (item.State == (int)MaintainDataStateEnum.Confirmed)),
                        query, isWithChild);
            }
        }

        public static GridModel<object> SubmitSelect(JosnPagingQueryModel query)
        {
            Guid targetID;
            var isWithChild = Helper.IsNeedOrganizationQuery(query, out targetID);
            List<Guid> organization = OrganizationHelper.GetAllowedOrganizationList(isWithChild, targetID);

            using (var context = new SausageEntities())
            {
                return
                    QueryMaintainMachine(
                        context.MaintainMachine.Where(
                            item =>
                            organization.Contains(item.OrganizationID) &&
                            (item.State == (int)MaintainDataStateEnum.Unsubmit ||
                             item.State == (int)MaintainDataStateEnum.AuditRejected)),
                        query, isWithChild);
            }
        }

        public static GridModel<object> AuditSelect(JosnPagingQueryModel query)
        {
            Guid targetID;
            var isWithChild = Helper.IsNeedOrganizationQuery(query, out targetID);
            List<Guid> organization = OrganizationHelper.GetAllowedOrganizationList(isWithChild, targetID);

            using (var context = new SausageEntities())
            {
                return
                    QueryMaintainMachine(context.MaintainMachine.Where(item =>
                    organization.Contains(item.OrganizationID) &&
                    (item.State == (int)MaintainDataStateEnum.Submitted ||
                     item.State == (int)MaintainDataStateEnum.ConfirmationRejected))
                    , query, isWithChild);
            }
        }

        public static GridModel<object> ConfirmSelect(JosnPagingQueryModel query)
        {
            Guid targetID;
            var isWithChild = Helper.IsNeedOrganizationQuery(query, out targetID);
            List<Guid> organization = OrganizationHelper.GetAllowedOrganizationList(isWithChild, targetID);

            using (var context = new SausageEntities())
            {
                return
                    QueryMaintainMachine(context.MaintainMachine.Where(item =>
                    organization.Contains(item.OrganizationID) && item.State == (int)MaintainDataStateEnum.Audited)
                    , query, isWithChild);
            }
        }

        private static GridModel<object> QueryMaintainMachine(IQueryable<MaintainMachine> source, JosnPagingQueryModel query, bool isWithChild)
        {
            var result = UIHelper.GetGridModelFromQueryModel<MaintainMachine>(
                source,
                query.page,
                query.limit,
                GetSortDescriptorFromQueryModel(query.SortModel),
                GetSearchFilterFromQueryModel(query.FilterModel, isWithChild));

            var list = result.Data.Select(maintainMachine => new
            {
                MaintainMachineID = maintainMachine.MaintainMachineID,
                QuantityID = maintainMachine.QuantityID,
                OrganizationID = maintainMachine.OrganizationID,
                Organization = maintainMachine.Organization.OrganizationName,
                MachineID = maintainMachine.MachineID,
                Machine = maintainMachine.Machine.ItemName,
                MachineTypeID = maintainMachine.MachineTypeID,
                MachineType = maintainMachine.MachineType.ItemName,
                MachineUnitID = maintainMachine.MachineUnitID,
                MachineUnit = maintainMachine.Unit.ItemName,
                MaintainCode = maintainMachine.MaintainQuantity.MaintainCode,
                Quantity = maintainMachine.Quantity,
                Price = maintainMachine.Price,
                Amount = maintainMachine.Amount,
                OilTypeID = maintainMachine.OilType,
                OilType = maintainMachine.Oil.ItemName,
                OilPrice = maintainMachine.OilPrice,
                OilWear = maintainMachine.OilWear,
                OilAmount = maintainMachine.OilAmount,
                MaintenanceCost = maintainMachine.MaintenanceCost,
                CreateDate = maintainMachine.CreateDate,
                Applicant = maintainMachine.Applicant,
                ApplicationDate = maintainMachine.ApplicationDate,
                Auditor = maintainMachine.Auditor,
                AuditedDate = maintainMachine.AuditedDate,
                Approver = maintainMachine.Approver,
                ApprovedDate = maintainMachine.ApprovedDate,
                State = maintainMachine.State,
                IsDelay = maintainMachine.IsDelay,
                Memo = maintainMachine.Memo,
                maintainMachine.Comment
            }).ToList();

            return new GridModel<object>()
            {
                Aggregates = result.Aggregates,
                Data = list,
                Total = result.Total
            };
        }

        private static List<IFilterDescriptor> GetSearchFilterFromQueryModel(IEnumerable<JosnQueryFilterModel> filterModels, bool isWithChild)
        {
            var filterList = new List<IFilterDescriptor>();
            foreach (var item in filterModels)
            {
                if (string.IsNullOrEmpty(item.value))
                    continue;

                if (item.property == "OrganizationID" && isWithChild)
                    continue;

                if (item.property.EndsWith("ID", StringComparison.InvariantCultureIgnoreCase))
                {
                    var targetID = Guid.Parse(item.value);
                    if (targetID != Guid.Empty)
                        filterList.Add(new FilterDescriptor(item.property, FilterOperator.IsEqualTo, targetID));
                }
                else if (item.property == "ApplicationDate_L") //startData - begin
                {
                    var targetDate = DateTime.Parse(item.value);
                    filterList.Add(new FilterDescriptor("ApplicationDate", FilterOperator.IsGreaterThanOrEqualTo, targetDate));
                }
                else if (item.property == "ApplicationDate_H") // startDate - end.
                {
                    var targetDate = DateTime.Parse(item.value);
                    filterList.Add(new FilterDescriptor("ApplicationDate", FilterOperator.IsLessThanOrEqualTo, targetDate));
                }
                else //other filter.
                    filterList.Add(new FilterDescriptor(item.property, FilterOperator.Contains, item.value));
            }
            return filterList;
        }

        private static List<SortDescriptor> GetSortDescriptorFromQueryModel(IEnumerable<JosnQuerySortModel> sortModels)
        {
            //convert the sort description.
            var sortList = new List<SortDescriptor>();
            foreach (var item in sortModels)
            {
                var descriptor = new SortDescriptor()
                {
                    Member = item.property,
                    SortDirection =
                        item.direction.ToLower() == "desc"
                            ? ListSortDirection.Descending
                            : ListSortDirection.Ascending
                };

                if (descriptor.Member == "Organization")
                    descriptor.Member = "Organization.OrganizationName";
                else if (descriptor.Member == "MaintainCode")
                    descriptor.Member = "MaintainQuantity.MaintainCode";
                else if (descriptor.Member == "Machine")
                    descriptor.Member = "Machine.ItemName";
                else if (descriptor.Member == "MachineType")
                    descriptor.Member = "MachineType.ItemName";

                sortList.Add(descriptor);
            }

            return sortList;

        }

        public static void DeleteMaintainMachine(Guid id)
        {
            using (var context = new SausageEntities())
            {
                var maintainMachine = new MaintainMachine();
                maintainMachine.MaintainMachineID = id;

                context.CreateObjectSet<MaintainMachine>().Attach(maintainMachine);
                context.ObjectStateManager.ChangeObjectState(maintainMachine, EntityState.Deleted);
                context.SaveChanges();
            }
        }

        public static MaintainMachine GetMaintainMachineByID(Guid id)
        {
            using (var context = new SausageEntities())
            {
                return
                    context.MaintainMachine.Include("Organization").Include("MaintainQuantity").Include("Machine").Include("MachineType").Include("Oil").
                        FirstOrDefault(maintainMachine => maintainMachine.MaintainMachineID == id);
            }
        }

        public static void UpdateMaintainMachine(MaintainMachineListRow data)
        {
            using (var context = new SausageEntities())
            {
                var maintainMachine =
                    context.MaintainMachine.FirstOrDefault(item => item.MaintainMachineID == data.MaintainMachineID);
                if (maintainMachine == null)
                    return;

                if (maintainMachine.State != (int)MaintainDataStateEnum.Unsubmit && maintainMachine.State != (int)MaintainDataStateEnum.AuditRejected)
                    throw new SausageException(string.Format("养护机械已经提交，不允许执行编辑操作。"));


                maintainMachine.QuantityID = data.QuantityID;
                maintainMachine.MachineID = data.MachineID;
                maintainMachine.MachineTypeID = data.MachineTypeID;
                maintainMachine.MachineUnitID = data.MachineUnitID;
                maintainMachine.Quantity = data.Quantity;
                maintainMachine.Price = data.Price;
                maintainMachine.Amount = data.Quantity * data.Price;
                maintainMachine.OilType = data.OilTypeID;
                maintainMachine.OilPrice = data.OilPrice;
                maintainMachine.OilWear = data.OilWear;
                maintainMachine.OilAmount = data.OilPrice * data.OilWear;
                maintainMachine.MaintenanceCost = data.MaintenanceCost;
                maintainMachine.Applicant = Helper.CurrentPrincipal.User.UserName;
                //maintainMachine.ApplicationDate = data.ApplicationDate;
                maintainMachine.Memo = data.Memo;

                context.SaveChanges();
            }
        }

        public static void UpdateMaintainMachineState(Guid id, int state)
        {
            using (var context = new SausageEntities())
            {
                var maintainMachine = context.MaintainMachine.FirstOrDefault(item => item.MaintainMachineID == id);
                if (maintainMachine == null)
                    return;

                maintainMachine.State = state;
                context.SaveChanges();
            }
        }

        public static void CreateMaintainMachine(MaintainMachineListRow data)
        {
            using (var context = new SausageEntities())
            {

                MaintainMachine entity = new MaintainMachine();

                entity.MaintainMachineID = Guid.NewGuid();
                entity.QuantityID = data.QuantityID;
                entity.OrganizationID = Helper.CurrentPrincipal.Organization.OrganizationID;
                entity.MachineID = data.MachineID;
                entity.MachineUnitID = data.MachineUnitID;
                entity.MachineTypeID = data.MachineTypeID;
                entity.Quantity = data.Quantity;
                entity.Price = data.Price;
                entity.Amount = data.Quantity * data.Price;
                entity.OilType = data.OilTypeID;
                entity.OilPrice = data.OilPrice;
                entity.OilWear = data.OilWear;
                entity.OilAmount = data.OilPrice * data.OilWear;
                entity.MaintenanceCost = data.MaintenanceCost;
                entity.CreateDate = DateTime.Now;
                entity.Applicant = Helper.CurrentPrincipal.User.UserName;
                entity.ApplicationDate = data.ApplicationDate;
                entity.State = (int)MaintainDataStateEnum.Unsubmit;
                entity.IsDelay = Helper.IsDelay(data.ApplicationDate);
                entity.Memo = data.Memo;

                context.AddToMaintainMachine(entity);
                context.SaveChanges();
            }
        }

        public static void ExecuteSubmit(Guid[] machines)
        {
            if (null != machines && machines.Length > 0)
            {
                using (var context = new SausageEntities())
                {
                    var list = context.MaintainMachine.Where(item => machines.Contains(item.MaintainMachineID)).ToList();

                    foreach (var entity in list)
                    {
                        entity.State = (int)MaintainDataStateEnum.Submitted;
                    }
                    context.SaveChanges();
                }
            }
        }

        public static void ExecuteAudit(Guid[] machines, bool passed, string comment)
        {
            if (null != machines && machines.Length > 0)
            {
                using (var context = new SausageEntities())
                {
                    var list = context.MaintainMachine.Where(item => machines.Contains(item.MaintainMachineID)).ToList();

                    foreach (var maintainMachine in list)
                    {
                        maintainMachine.Auditor = Helper.CurrentPrincipal.User.UserName;
                        maintainMachine.AuditedDate = DateTime.Now;
                        maintainMachine.Comment = comment;
                        maintainMachine.State = passed
                                                     ? (int)MaintainDataStateEnum.Audited
                                                     : (int)MaintainDataStateEnum.AuditRejected;
                    }
                    context.SaveChanges();
                }
            }
        }

        public static void ExecuteConfirm(Guid[] machines, bool passed, string comment)
        {
            if (null != machines && machines.Length > 0)
            {
                using (var context = new SausageEntities())
                {
                    var list = context.MaintainMachine.Where(item => machines.Contains(item.MaintainMachineID)).ToList();

                    foreach (var maintainMachine in list)
                    {
                        maintainMachine.Approver = Helper.CurrentPrincipal.User.UserName;
                        maintainMachine.ApprovedDate = DateTime.Now;
                        maintainMachine.Comment = comment;
                        maintainMachine.State = passed
                                                     ? (int)MaintainDataStateEnum.Confirmed
                                                     : (int)MaintainDataStateEnum.ConfirmationRejected;
                    }
                    context.SaveChanges();
                }
            }
        }
    }
}